package by.sjc.giz.web.controller;

import by.sjc.giz.model.Account;
import by.sjc.giz.model.Cart;
import by.sjc.giz.model.Order;
import by.sjc.giz.model.Subject;
import by.sjc.giz.model.SubjectType;
import by.sjc.giz.model.payment.Payment;
import by.sjc.giz.model.payment.PaymentMethod;
import by.sjc.giz.model.shop.BookInShopListWrapper;
import by.sjc.giz.security.CustomUserDetails;
import by.sjc.giz.service.OrderService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.List;

/**
 * Created by irina on 17.08.14.
 */
@Controller
@PreAuthorize("isFullyAuthenticated()")
@RequestMapping("/order")
public class OrderController {

    public static final Logger logger = Logger.getLogger(OrderController.class);

    @Autowired
    private OrderService orderService;

    @RequestMapping(value = "/payment", method = { RequestMethod.GET })
    public ModelAndView orderPayment(Authentication authentication) {

        logger.debug("order payment");
        ModelAndView mav = new ModelAndView();
        mav.addObject("paymentMethods", PaymentMethod.values());

        Account account = ((CustomUserDetails) authentication.getPrincipal()).getAccount();
        assert null != account;

        mav.addObject("payment", new Payment());
        if (account.getCart().getBooks().isEmpty()) {
            mav.setViewName("cart");
        } else {
            mav.setViewName("order.payment");
            mav.addObject("address", "");
        }
        return mav;
    }

    @RequestMapping(value = "/payment", method = { RequestMethod.POST })
    public ModelAndView orderPayment(HttpSession session,
                                     @Valid Payment payment,
                                     BindingResult result,
                                     @RequestParam String address) {

        ModelAndView mav = new ModelAndView();
        if (result.hasErrors() || "".equals(address.trim())) {
            mav.addObject("paymentMethods", PaymentMethod.values());
            mav.setViewName("order.payment");
            mav.addObject("message", "Enter your address");
        } else {
            session.setAttribute("payment", payment);
            session.setAttribute("address", address);
            mav.setViewName("order.confirm");
        }
        return mav;
    }

    @RequestMapping(value = "/new")
    public ModelAndView newOrder(Authentication authentication,
                                 HttpSession session) {

        logger.info("creating new order");
        ModelAndView mav = new ModelAndView();

        Account account = ((CustomUserDetails) authentication.getPrincipal()).getAccount();
        assert null != account;

        Payment payment = (Payment) session.getAttribute("payment");
        String address = (String) session.getAttribute("address");

        Subject subject = account.getSubject();
        if (subject.getType() == SubjectType.SHOP) {
            BookInShopListWrapper books =
                    orderService.makeOrderFromShopToPublisher(account, payment, address);

            if (books.getBookInShopList().size() != 0) {
                mav.addObject("books", books);
                mav.setViewName("shop.books.prices");
            } else {
                mav.setViewName("redirect:/order/outgoing");
            }
        } else {
            orderService.makeOrder(account, payment, address);
            mav.setViewName("redirect:/order/outgoing");
        }

        account.setCart(new Cart());
        session.removeAttribute("payment");
        session.removeAttribute("address");

        return mav;
    }

    @RequestMapping(value={"/incoming"})
    public ModelAndView listIncomingOrders(
            Authentication authentication ) {
        Subject subject = ((CustomUserDetails) authentication.getPrincipal()).getAccount().getSubject();

        List<Order> orders = orderService.getIncomingOrders(subject.getId());

        ModelAndView mav = new ModelAndView();
        mav.setViewName("order.list.incoming");
        mav.addObject("orders", orders);
        mav.addObject("subject", subject);

        return mav;
    }

    @RequestMapping(value={"/outgoing"})
    public ModelAndView listOutgoingOrders(
            Authentication authentication ) {
        Subject subject = ((CustomUserDetails) authentication.getPrincipal()).getAccount().getSubject();

        List<Order> orders = orderService.getOutgoingOrders(subject.getId());

        ModelAndView mav = new ModelAndView();
        mav.setViewName("order.list.outgoing");
        mav.addObject("orders", orders);
        mav.addObject("subject", subject);

        return mav;
    }

    @RequestMapping(value={"/archive/incoming"})
    public ModelAndView listArchiveIncomingOrders(
            Authentication authentication ) {
        Subject subject = ((CustomUserDetails) authentication.getPrincipal()).getAccount().getSubject();

        ModelAndView mav = new ModelAndView();

        List<Order> orders = orderService.getCompletedIncomingOrders(subject.getId());

        mav.setViewName("order.archive");
        mav.addObject("orders", orders);
        mav.addObject("subject", subject);

        return mav;
    }

    @RequestMapping(value={"/archive/outgoing"})
    public ModelAndView listArchiveOutgoingOrders(
            Authentication authentication ) {
        Subject subject = ((CustomUserDetails) authentication.getPrincipal()).getAccount().getSubject();

        ModelAndView mav = new ModelAndView();

        List<Order> orders = orderService.getCompletedOutgoingOrders(subject.getId());

        mav.setViewName("order.archive");
        mav.addObject("orders", orders);
        mav.addObject("subject", subject);

        return mav;
    }
}
